/***************************************************************************
 * The Open Armory API is a project to retrieve World of Warcraft(R) 
 * related XML data from The Armory.
 * 
 * The data retrieved via the Open Armory API from The Armory is 
 * proprietary to Blizzard Entertainment, Inc(R).
 * *************************************************************************
 * Copyright (C) 2009 - 2010 Tedla M.B. Brandsema
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ***************************************************************************/
package net.openarmory.core.domain.url;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import net.openarmory.core.config.ConfigurationProperties;
import net.openarmory.core.domain.constants.ArmoryIconSize;
import net.openarmory.core.domain.constants.ArmoryPortraitLevel;
import net.openarmory.core.domain.constants.ArmoryZone;
import net.openarmory.core.domain.constants.CharacterClass;
import net.openarmory.core.domain.constants.CharacterGender;
import net.openarmory.core.domain.constants.CharacterRace;
import net.openarmory.core.domain.validation.InvalidRaceClassCombinationException;
import net.openarmory.core.domain.validation.RaceClassCombination;

import org.apache.log4j.Logger;

// TODO: Auto-generated Javadoc
/**
 * The Class ArmoryImageUrlBuilder.
 */
public final class ArmoryImageUrlBuilder extends ArmoryUrlBuilder {

	/** The log. */
	private static final Logger LOG = Logger
			.getLogger(ArmoryImageUrlBuilder.class);

	/** The zone. */
	private ArmoryZone zone;

	/** The icon size. */
	private ArmoryIconSize iconSize;

	/** The icon name. */
	private String iconName;

	/** The portrait level. */
	private ArmoryPortraitLevel portraitLevel;

	/** The gender. */
	private CharacterGender gender;

	/** The race. */
	private CharacterRace race;

	/** The clazz. */
	private CharacterClass clazz;

	/** The config. */
	private ConfigurationProperties config = null;

	/**
	 * Gets the zone.
	 * 
	 * @return the zone
	 */
	public ArmoryZone getZone() {
		return this.zone;
	}

	/**
	 * Gets the icon size.
	 * 
	 * @return the icon size
	 */
	public ArmoryIconSize getIconSize() {
		return this.iconSize;
	}

	/**
	 * Gets the icon name.
	 * 
	 * @return the icon name
	 */
	public String getIconName() {
		return this.iconName;
	}

	/**
	 * Gets the portrait level.
	 * 
	 * @return the portrait level
	 */
	public ArmoryPortraitLevel getPortraitLevel() {
		return this.portraitLevel;
	}

	/**
	 * Gets the gender.
	 * 
	 * @return the gender
	 */
	public CharacterGender getGender() {
		return this.gender;
	}

	/**
	 * Gets the race.
	 * 
	 * @return the race
	 */
	public CharacterRace getRace() {
		return this.race;
	}

	/**
	 * Gets the clazz.
	 * 
	 * @return the clazz
	 */
	public CharacterClass getClazz() {
		return this.clazz;
	}

	/**
	 * Gets the config.
	 * 
	 * @return the config
	 */
	public ConfigurationProperties getConfig() {
		return this.config;
	}

	/**
	 * Instantiates a new armory image url builder.
	 */
	public ArmoryImageUrlBuilder() {
		try {
			this.config = ConfigurationProperties.getInstance();
		} catch (final IOException e) {
			LOG.fatal("Can not open/find configuration file.", e);
		}
	}

	/**
	 * Builds the icon url.
	 * 
	 * @param zone
	 *            the zone
	 * @param iconSize
	 *            the icon size
	 * @param iconName
	 *            the icon name
	 * @return the uRL
	 */
	public ArmoryIconUrl getIconUrl(final ArmoryZone zone,
			final ArmoryIconSize iconSize, final String iconName) {
		final ArmoryIconUrl armoryIconUrl = new ArmoryIconUrl();
		this.zone = zone;
		this.iconSize = iconSize;
		this.iconName = iconName;

		try {
			armoryIconUrl.setUrl(new URL(zone.getUrlConfigProperty()
					+ this.config.getIconUrlPath()
					+ iconSize.getUrlConfigProperty() + urlEncode(iconName)
					+ iconSize.getFileFormat()));
		} catch (final MalformedURLException e) {
			LOG.fatal("Malformed icon url", e);
		}
		return armoryIconUrl;
	}

	/**
	 * Builds the portrait url.
	 * 
	 * @param zone
	 *            the zone
	 * @param portraitLevel
	 *            the portrait level
	 * @param gender
	 *            the gender
	 * @param race
	 *            the race
	 * @param clazz
	 *            the clazz
	 * @return the uRL
	 */
	public ArmoryPortraitUrl getPortraitUrl(final ArmoryZone zone,
			final ArmoryPortraitLevel portraitLevel,
			final CharacterGender gender, final CharacterRace race,
			final CharacterClass clazz) {
		final ArmoryPortraitUrl armoryPortraitUrl = new ArmoryPortraitUrl();
		this.zone = zone;
		this.portraitLevel = portraitLevel;
		this.gender = gender;
		this.race = race;
		this.clazz = clazz;
		try {

			raceClassValidationHandler(race, clazz);

			armoryPortraitUrl.setUrl(new URL(zone.getUrlConfigProperty()
					+ this.config.getPortraitUrlPath()
					+ portraitLevel.getUrlConfigProperty()
					+ buildGenderRaceClassCombination(gender, race, clazz)
					+ this.config.getPortraitExtension()));

		} catch (final InvalidRaceClassCombinationException e) {
			LOG.fatal("Invalid race class combination: ", e);
		} catch (final MalformedURLException e) {
			LOG.fatal("Malformed icon url", e);
		}
		return armoryPortraitUrl;
	}

	/**
	 * Builds the gender race class combination.
	 * 
	 * @param gender
	 *            the gender
	 * @param race
	 *            the race
	 * @param clazz
	 *            the clazz
	 * @return the string
	 */
	private String buildGenderRaceClassCombination(
			final CharacterGender gender, final CharacterRace race,
			final CharacterClass clazz) {
		// TODO: check for invalid race class combination
		return gender.getNumericalRepresentation() + "-" + race.getNumericalRepresentation() + "-"
				+ clazz.getNumericalRepresentation();
	}

	/**
	 * Race class validation handler.
	 * 
	 * @param race
	 *            the race
	 * @param clazz
	 *            the clazz
	 * @throws InvalidRaceClassCombinationException
	 *             the invalid race class combination exception
	 */
	private void raceClassValidationHandler(final CharacterRace race,
			final CharacterClass clazz)
			throws InvalidRaceClassCombinationException {
		if (!RaceClassCombination.validateRaceClassCombination(race, clazz)) {
			throw new InvalidRaceClassCombinationException(
					"The race class combination of " + race.toString()
							+ " and " + clazz.toString() + " is not valid.");
		}
	}
}
